/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Description:                                                          *
 * Helper for wrapping the boost interval library with Cython.           *
 *                                                                       *
 * Author:                                                               *
 *     Harald Schilly - harald.schilly@gmail.com                         *
 *     2008, Vienna, Austria                                             *
 *                                                                       *
 * Copyright: ALL RIGHTS RESERVED                                        *
 * License:   GPL v2+ (http://www.gnu.org/licenses/gpl-2.0.html)         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <boost/numeric/interval.hpp>
#include <boost/numeric/interval/utility.hpp>
#include <utility>


#include <iostream>

#ifndef _BOOST_INTERVAL_WRAPPER_HELPER_
#define	_BOOST_INTERVAL_WRAPPER_HELPER_

#ifdef	__cplusplus
extern "C" {
#endif

  using namespace boost;
  using namespace numeric;
  using namespace interval_lib;

  // default policies to work with basic operations, trigonometric, ...
  typedef interval <double, policies<save_state<rounded_transc_opp<double> >, checking_base<double> > > IVD;

  /*
   * helper
   */
  typedef std::pair<IVD, IVD> i_pair;
  
  /*
   * initalizers
   */

  inline void init_c(IVD ivd) {
    ivd = IVD();
  }

  inline IVD* init_c_2(double l, double u) {
    return new IVD(l, u);
  }

  /*
   * basic manipulators
   */

  inline void set_c(IVD *i, double l, double u) {
    i->assign(l, u);
  }

  /*
   * with other intervals
   */
  inline IVD intersect_c(IVD *i1, IVD *i2) {
    return intersect(*i1, *i2);
  }

  /*
   * unary operators
   */

  inline double median(IVD *i) {
    return median(*i);
  }

  inline double width(IVD *i) {
    return width(*i);
  }

  inline double norm(IVD *i) {
    return norm(*i);
  }

  inline IVD widen_c(IVD* ivd, double w) {
    return widen(*ivd, w);
  }

  inline IVD sin_c(IVD *ivd) {
    return sin(*ivd);
  }

  inline IVD cos_c(IVD *ivd) {
    return cos(*ivd);
  }

  inline IVD tan_c(IVD *ivd) {
    return tan(*ivd);
  }

  inline IVD sqrt_c(IVD* ivd) {
    return sqrt(*ivd);
  }

  inline bool singleton(IVD *i) {
    return singleton(*i);
  }

  inline bool subset_c(IVD *self, IVD *other) {
    return subset(*self, *other);
  }

  inline bool in_c(double d, IVD *i) {
    return in(d, *i);
  }

  inline bool overlap_c(IVD *a, IVD *b) {
    return overlap(*a, *b);
  }
    
  /*
   *binary operators
   */

  inline IVD add_op(IVD *l, IVD *r) {
    return *l + *r;
  }

  inline IVD sub_op(IVD *l, IVD *r) {
    return *l - *r;
  }

  inline IVD mul_op(IVD *l, IVD *r) {
    return *l * *r;
  }

  inline IVD div_op(IVD *l, IVD *r) {
    return *l / *r;
  }

  inline IVD pow_op(IVD *i, int e) {
    return pow(*i, e);
  }

  inline IVD square(IVD *i) {
    return square(*i);
  }

  inline void printivd(IVD *ivd) {
    std::cout << "[" << ivd->lower() << " ~ " << ivd->upper() << "]" << std::endl;
  }

  inline i_pair bisect_c(IVD *ivd) {
    return bisect(*ivd);
  }



#ifdef	__cplusplus
}
#endif

#endif	/* _BOOST_INTERVAL_WRAPPER_HELPER_ */

